`timescale 1ns/1ns

module adder_tree_3(
    input  wire                  clk,
    input  wire                  rst_n,
    input  wire [32*56-1:0]      data,
    output reg  [64-1:0]         sum_out
);
    localparam NUM_INPUTS = 32;
    localparam DATA_WIDTH = 56;
    localparam OUT_WIDTH  = 64;          // 输出累加宽度

    genvar i;

    // Stage1: 32 -> 16 -> 8 (组合逻辑) & pipeline register #1
    wire signed [OUT_WIDTH-1:0] s1_16 [0:15];
    generate
        for(i=0;i<16;i=i+1) begin: G_L1
            wire signed [DATA_WIDTH-1:0] a = data[(2*i)*DATA_WIDTH +: DATA_WIDTH];
            wire signed [DATA_WIDTH-1:0] b = data[(2*i+1)*DATA_WIDTH +: DATA_WIDTH];
            assign s1_16[i] = {{(OUT_WIDTH-DATA_WIDTH){a[DATA_WIDTH-1]}},a} +
                               {{(OUT_WIDTH-DATA_WIDTH){b[DATA_WIDTH-1]}},b};
        end
    endgenerate

    wire signed [OUT_WIDTH-1:0] s2_8 [0:7];
    generate
        for(i=0;i<8;i=i+1) begin: G_L2
            assign s2_8[i] = s1_16[2*i] + s1_16[2*i+1];
        end
    endgenerate

    reg signed [OUT_WIDTH-1:0] r1 [0:7];
    integer k1;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            for(k1=0;k1<8;k1=k1+1) r1[k1] <= 0;
        else
            for(k1=0;k1<8;k1=k1+1) r1[k1] <= s2_8[k1];
    end

    // Stage2: (8 -> 4 -> 2 -> 1) & pipeline register #2 (sum_out)
    wire signed [OUT_WIDTH-1:0] s3_4 [0:3];
    generate
        for(i=0;i<4;i=i+1) begin: G_L3
            assign s3_4[i] = r1[2*i] + r1[2*i+1];
        end
    endgenerate

    wire signed [OUT_WIDTH-1:0] s4_2 [0:1];
    assign s4_2[0] = s3_4[0] + s3_4[1];
    assign s4_2[1] = s3_4[2] + s3_4[3];
    wire signed [OUT_WIDTH-1:0] s5_1 = s4_2[0] + s4_2[1];

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            sum_out <= 0;
        else
            sum_out <= s5_1;
    end
endmodule
